#region

using System.Net;
using System.Net.Mail;
using System.Text;
using Mapster;
using Microsoft.Extensions.Options;
using Vin.Extension.Cache;
using Vin.Extension.Email.Options;
using Vin.Extension.Email.Service;
using Vin.Extension.Framework.Sms.Model;
using Vin.Extension.Framework.Sms.Service;
using Vin.Tool.Attributes;
using Vin.Tool.Core.AssertCategory;
using Vin.Tool.Core.BasicTypeCategory;
using Vin.Tool.Core.ExceptionCategory;
using Vin.Tool.Core.JsonCategory;
using Vin.Tool.Core.RandomCategory;
using Vin.Tool.Domain.ExceptionModel;
using VinEmailOption = Vin.Extension.Framework.Sms.Email.Model.VinEmailOption;

#endregion

namespace Vin.Extension.Framework.Sms.Email.Service;

[Service(Key)]
public class VinEmailSmsService : VinSmsService
{
    public const string Key = "vin-email-sms";

    [Inject] private readonly IOptionsMonitor<VinEmailOption> _optionsMonitor = null!;

    [Inject] private readonly VinEmailService _vinEmailService = null!;

    private VinEmailOption Option => _optionsMonitor.CurrentValue;

    private string CacheKey(string key) => Option.CacheCodeKey + key;

    public override async Task<string> SendCodeAsync(string businessDesc, string receiver, VinSmsSendOption? option = null)
    {
        await base.SendCodeAsync(businessDesc, receiver, option);

        var key = Guid.NewGuid().ToString("N");
        var code = RandomTool.RandomLong(100000, 1000000);
        // 获取验证码
        CacheFactory.SetCache<string>(CacheKey(key), code.ToString(), TimeSpan.FromMinutes(SmsConfig.Code.Expire));
        await SendEmail(key, businessDesc, new List<string>() { receiver }, SmsConfig.Code.Title,
            SmsConfig.Code.Content, new
            {
                Code = code,
                SmsConfig.Code.Expire
            }, option);
        return key;
    }

    public override async Task<bool> VerifyCodeAsync(string uuid, string code)
    {
        var cacheKey = CacheKey(uuid);
        var cacheCode = CacheFactory.GetCache<string>(cacheKey);
        if (cacheCode.IsNullOrWhiteSpace())
        {
            return false;
        }

        if (cacheCode!.Equals(code, StringComparison.OrdinalIgnoreCase))
        {
            CacheFactory.RemoveCache(cacheKey);
            return true;
        }

        return await Task.FromResult(false);
    }

    public override async Task SendAsync(string businessDesc, string receiver, string title, string content,
        object data, VinSmsSendOption? option = null)
    {
        await SendAsync(businessDesc, new List<string>() { receiver }, title, content, data, option);
    }

    public override async Task SendAsync(string businessDesc, List<string> receivers, string title, string content,
        object data, VinSmsSendOption? option = null)
    {
        await SendEmail(Guid.NewGuid().ToString("N"), businessDesc, receivers, title, content, null, option);
    }

    // -------------------------- 私有方法 --------------------------
    private async Task SendEmail(string businessId, string businessDesc, List<string> receivers, string title,
        string template, object? templateData, VinSmsSendOption? option = null)
    {
        var content = template.Format(templateData);
        if (option is not Model.VinEmailSendOption emailOption) return;

        // var emailOption = option.Adapt<VinEmailSendOption>();
        try
        {
            await _vinEmailService.SendEmail(receivers, title, template, templateData, emailOption.Adapt<VinEmailSendOption>());

            await SaveLogAsync(businessId, businessDesc, _vinEmailService.Option.Sender, "Email",
                emailOption.Receivers.Count > 0
                    ? emailOption.Receivers.ToCamelCaseJson()
                    : receivers.ToCamelCaseJson(),
                title, content, true, "发送成功",
                template, templateData, emailOption);
        }
        catch (System.Exception ex)
        {
            await SaveLogAsync(businessId, businessDesc, _vinEmailService.Option.Sender, "Email",
                emailOption.Receivers.Count > 0
                    ? emailOption.Receivers.ToCamelCaseJson()
                    : receivers.ToCamelCaseJson(),
                title, content, false, ex.ExceptionMessage(),
                template, templateData, emailOption);
            throw;
        }
    }
}